import RouterLink from "./components/RouterLink"
import RouterView from "./components/RouterView"
import { creatematcher } from "./create-matcher"
import HashHistory from "./history/hash"
import BrowserHistroy from "./history/history"

export let Vue

// new 时产生 路由实例
class VueRouter {

  /**
   * 扁平化路由
   * 
   * @param {*} options 
   */
  constructor(options = {}) {
    // {'/': record, '/about': record, '/about/a': record}  拍平处理
    this.matcher = creatematcher(options.routes || [])

    // 默认有三种，先实现 hash history
    if (options.mode === 'hash') {
      this.history = new HashHistory(this)
    } else {
      this.history = new BrowserHistroy(this)
    }

    // 匹配规则
  }

  match(location) {
    return this.matcher.match(location)
  }

  push(location) {
    this.history.transitionTo(location, () => {
      this.history.updateLocation(location)
    })
  }

  init(app) {
    // 监听路径变化，渲染对应组件
    const history = this.history

    // 监听回调   _route 是响应式的数据
    history.listen((route) => {
      /**
       * _route = A
       * 修改路径后  A = B 不会引起响应式
       * _route = B
       */
      app._route = route
    })

    const setupListenerHandler = () => {
      history.setupListener() // 监听 hash 变化。  路由自己内部的处理
    }

    // 老版本中 hashchange, 新版本使用 popstate
    // 根据路径进行跳转，跳转完毕后监听 hash 变化
    history.transitionTo(history.getCurrentLocation(), setupListenerHandler) // 根据当前路径匹配
  }
}

////// 1.
VueRouter.install = (_Vue) => {
  Vue = _Vue

  // router-view  router-link
  Vue.component('router-link', RouterLink)

  Vue.component('router-view', RouterView)

  // 后面使用 router 实例时，组件用的都是同一个

  Vue.mixin({
    beforeCreate() {
      if (this.$options.router) {
        // root

        this._routerRoot = this // 将自己暴露出去
        this._router = this.$options.router // 自己添加 _router 属性

        this._router.init(this) // new Vue 实例传入

        // 定义响应式
        Vue.util.defineReactive(this, '_route', this._router.history.current)
        console.log(this._route, 99)
      } else {
        // child  component

        this._routerRoot = this.$parent && this.$parent._routerRoot

        // 子组件通过 this._routerRoot._router 调用
      }
    }
  })


  // 代理到原型了，没有绑定

  // 方便组件内 取值， {path: '/', matched: [], params, query}
  Object.defineProperty(Vue.prototype, '$route', {
    get() {
      return this._routerRoot._route
    }
  })

  Object.defineProperty(Vue.prototype, '$router', {
    get() {
      return this._routerRoot._router // match  push  replace
    }
  })
}

// father store ->  child store -> 
// 父 router  this._routerRoot 绑定在自己身上
// child  $parent._routerRoot, get  parent props

export default VueRouter


/**
 * 初始化 执行 init  根据当前的路径
 */




/**
 * 1. 构建类，混入 router
 * 2. 注册 router-view  router-link
 * 3. init 方法执行 vm
 * 
 * 4. match map  生成路由表。match 匹配
 */